/**
 * UsedTimeline module
 */

import React, {Component} from 'react';
import { connect } from 'dva';
import classnames from 'classnames';
import { bindActionCreators } from 'redux';
import timelineActions from '../../../actions/Editor/timelines';
import tool from '../../../utils/tool';

class UsedTimeline extends Component {
    constructor(props) {
        super(props);
        this.state = {             
            updateAllTimeline: false,
            draggable: false,
        };
    }
    getInitialState(){
        return {
            updateAllTimeline: false,
            draggable: false,
        }
    }
    initElements(){
        this.elements = {
            timeline: $(this.refs.timeline),
            handleLeft: $(this.refs.timeline).find(".ui-slider-handle-left"),
            handleRight: $(this.refs.timeline).find(".ui-slider-handle-right")
        };
    }
    componentWillMount(){
        this.min = 0;
        this.max = 60;
        this.step = 0.1;
        this.restore = {};
        this.duration = 0;
        this.handleLeft = null;
        this.handleRight = null;
        this.beforeTimeline = null;
        this.afterTimeline = null;
        this.timeline = this.props.timeline;
        this.lastLeft = this.timeline.start_time;
    }
    componentDidMount(){
        this.initElements();
        this.bindHandlesEvent();
        this.elements.timeline.draggable({
            containment: this.elements.timeline.parent(),
            axis: 'x',
            drag: (e, ui)=> this.rangeDrag(e, ui),
            start: (e, ui)=> this.onStartDrag(e, ui),
            stop: (e, ui)=> this.onStopDrag(e, ui)
        }).css({
            position: 'absolute'
        });
    }
    resetTriggeredColor(){
        let timelineNode = this.elements.timeline;
        let triggeredColor = timelineNode.attr("triggeredColor");
        if (triggeredColor){
            this.timeline.triggeredcolor = triggeredColor;
        } else {
            triggeredColor = this.timeline.triggeredcolor;
            if (triggeredColor){
                timelineNode.attr("triggeredColor", triggeredColor);
            }
        }
    }
    trimAlignValue(val) {
        var min = this.min, max = this.max;
        var alignValue, valModStep;

        if (val <= min) return min;
        if (val >= max) return max;

        this.step = (this.step > 0) ? this.step : 0.1;
        valModStep = (val - min) % this.step;
        alignValue = val - valModStep;

        if (Math.abs(valModStep) * 2 >= this.step) {
            alignValue += (valModStep > 0) ? this.step : (-this.step);
        }
        return parseFloat(alignValue.toFixed(5));
    }
    normValueFromMouse(val) {
        const {timelineTool} = this.props;
        const {scale} = timelineTool;
        
        val = val /scale * 100;
        var max = this.max;
        var timelineNode = this.elements.timeline;
        var valPercent = val / timelineNode.parent().width(),
            normValue = max * valPercent;

        return this.trimAlignValue(normValue);
    }
    refreshValue(left, right ,type) {
        let max = this.max;
        const {timelineTool} = this.props;
        const {scale} = timelineTool;
        let timelineNode = this.elements.timeline;
        if(!type && !this.checkLimit(left, right)) return;//timeline drag
        if(type && !this.checkDurationLimit(left,right)) return; //handle drag

        timelineNode.css({
            left: left / max * scale / 100 * 100 + '%',
            width: (this.timeline.end_time - this.timeline.start_time) / 60 * scale / 100 * 100 + '%',
        })
        this.handleLeft.css({
            left: left / max * scale / 100 * 100 + '%'
        });
        this.handleRight.css({
            left: right / max * scale / 100 * 100 + '%'
        });
        this.lastLeft = left ;
        this.timeline.start_time = left ;
        this.timeline.end_time = right ;
        this.timeline.duration = this.timeline.end_time - this.timeline.start_time;
        if (this.timeline.end_time > 60){
            this.duration = this.timeline.end_time - this.timeline.start_time;
            this.timeline.end_time = 60;
            this.timeline.start_time = 60 - this.duration;
        }
        this.timeline.start_time = parseFloat(this.timeline.start_time.toFixed(1));
        this.timeline.end_time = parseFloat(this.timeline.end_time.toFixed(1));
        this.timeline.duration = parseFloat(this.timeline.duration.toFixed(1));

        const {selecteWidgetTimeline} = this.props;
        selecteWidgetTimeline(this.timeline);
        this.updateTimelineWidth(this.timeline);
    }
    checkLimit(left, right) {
        const {timelineTool,timelines,timeline} = this.props;
        const {scale} = timelineTool;

        if (right - left < this.step) return false;
        if (this.beforeTimeline && left <= this.beforeTimeline.end_time) return false;
        if (this.afterTimeline && right >= this.afterTimeline.start_time) return false;
        if(timelines.length > 1){
            for(var i in timelines){
                i = parseInt(i);
                if(timeline.id == timelines[i].id){
                    if(i ==0 ){
                        if(right > parseFloat(timelines[i+1].start_time)){
                            return false;
                        }
                    } else {
                        if(left < parseFloat(timelines[i-1].end_time)){
                            return false;
                        }
                        if(i< timelines.length-1 && right > parseFloat(timelines[i+1].start_time)){
                            return false;
                        }
                    }
                }
            }
        }

        return true;
    }
    checkDurationLimit(left,right){
        var timelines = this.props.timelines ,
            timeline = this.props.timeline ,
            root =this.props.root,
            widget = this.props.widget;
        const {timelineTool} = this.props;
        const {scale} = timelineTool;
        if (right - left < this.step || right-left > 10) return false;
        if (this.beforeTimeline && left <= this.beforeTimeline.end_time) return false;
        if (this.afterTimeline && right >= this.afterTimeline.start_time) return false;
        if(timelines.length > 1){
            for(var i in timelines){
                i = parseInt(i);
                if(timeline.id == timelines[i].id){
                    if(i< timelines.length-1){
                        if(right > parseFloat(timelines[i+1].start_time)){
                            var index = right - parseFloat(timelines[i+1].start_time);
                            for(var j = i+1 ; j< timelines.length;j++){
                                timelines[j].end_time = parseFloat(timelines[j].end_time) + index;
                                timelines[j].start_time = parseFloat(timelines[j].start_time) + index;
                                timelines[j].duration = parseFloat(timelines[j].end_time) - parseFloat(timelines[j].start_time);
                            }
                        }
                    }
                    if(i>0){
                        if(left < parseFloat(timelines[i-1].end_time)){
                            return false;
                        }
                    }
                    this.setState({updateAllTimeline: true})
                }
            }
        }
        return true;
    }
    bindHandlesEvent() {
        const {timelineTool} = this.props;
        const {scale} = timelineTool;
        let handle = "<a href='#' class='ui-slider-handle'></a>";
        let timelineNode = this.elements.timeline;
        let max = this.max;
        this.handleLeft = $(handle);
        timelineNode.after(this.handleLeft);
        this.handleLeft.addClass('ui-slider-handle-left');
        this.handleLeft.css({
            left: (this.timeline.start_time / max * scale / 100 * 100) + '%',
            background: this.timeline.triggeredcolor || '#CECECE'
        });

        this.handleRight = $(handle);
        timelineNode.after(this.handleRight);
        this.handleRight.addClass('ui-slider-handle-right');
        this.handleRight.css({
            left: (this.timeline.end_time / max * scale / 100 * 100) + '%',
            background: this.timeline.triggeredcolor || '#CECECE'
        });
        this.handleLeft.draggable({
            containment: timelineNode.parent(),
            axis: 'x',
            drag: (e, ui)=> this.onRangeDrag(e, ui),
            start: (e, ui)=> this.onStartDrag(e, ui),
            stop: (e, ui)=> this.onStopDrag(e, ui)
        }).css({
            position: 'absolute'
        });

        this.handleRight.draggable({
            containment: timelineNode.parent(),
            axis: 'x',
            drag: (e, ui)=> this.onRangeDrag(e, ui),
            start: (e, ui)=> this.onStartDrag(e, ui),
            stop: (e, ui)=> this.onStopDrag(e, ui)
        }).css({
            position: 'absolute'
        });
    }
    onRangeDrag(e, ui) {
        var timelineNode = this.elements.timeline;
        var left, width, right;
        var dragTarget = $(ui.helper);
        if (dragTarget.hasClass('ui-slider-handle-left')) {
            left = this.normValueFromMouse(ui.position.left);
            width = this.normValueFromMouse(timelineNode.width());
            right = this.lastLeft + width;
        } else {
            right = this.normValueFromMouse(ui.position.left);
            width = this.normValueFromMouse(timelineNode.width());
            left = this.lastLeft;
        }
        var type = 1;
        this.refreshValue(left, right ,type);
    }
    rangeDrag(e,ui){
        var timelineNode = this.elements.timeline;
        var left = this.normValueFromMouse(ui.position.left),
            width = this.normValueFromMouse(timelineNode.width()),
            right = left + width;
        var type = 0;
        this.refreshValue(left, right ,type);
    }
    onStartDrag(e, ui) {
        this.restore = $.extend(true, {}, this.timeline);
        this.resetTriggeredColor();
        this.updateTimelineWidth(this.timeline);
    }
    onStopDrag(e, ui) {
        let oldTimeline = $.extend(true, {}, this.restore),
            newTimeline = $.extend(true, {}, this.timeline);
        let updateAllTimeline = this.state.updateAllTimeline;
        const { updateTimeline,updateTimelines,selecteWidgetTimeline,timelines} = this.props;

        // 更新timeline
        if(!updateAllTimeline){
            updateTimeline(this.timeline);
            
        } else {//修改持续时间，更新元件所有timeline
            let widget_id = this.timeline.widget_id;
            const widgetTimelines = timelines.filter(w => w.widget_id === widget_id);
            updateTimelines(widgetTimelines);
        }
        this.updateTimelineWidth(this.timeline);
    }
    updateTimelineWidth(timeline){
        let max = this.max;
        let timelineNode = this.elements.timeline;
        let triggeredColor = timelineNode.attr("triggeredColor");
        const {selectedTimelineId,timelineTool} = this.props;
        const {scale} = timelineTool;
        this.handleLeft.css({
            left: (timeline.start_time / max * scale / 100 * 100) + '%',
            background: timeline.triggeredcolor || '#CECECE'
        });
        this.handleRight.css({
            left: (timeline.end_time / max * scale / 100 * 100) + '%',
            background: timeline.triggeredcolor || '#CECECE'
        });
        timelineNode.css({
            left: (timeline.start_time / max * scale / 100 * 100) + '%',
            width: (timeline.end_time - timeline.start_time) / 60 * scale / 100 * 100 + '%',
            background: (selectedTimelineId == timeline.id ? "linear-gradient(to right, #f76b1c, #fb62a2)" : triggeredColor)
        });
    }
    render(){
        const {widget,widgets,timeline,timelineTool,selectedTimeline: pSelectTimeline,selectedTimelineId,selecteWidgetTimeline} = this.props;
        const { scale } = timelineTool;
        let selectedTimeline = pSelectTimeline || {};
        let max = this.max || 60;
        let triggeredColor = tool.getTriggerColorByTimeline(widgets,timeline)|| timeline.trigger_color;
        let rStyle = {
            left: (timeline.start_time / 60 * scale / 100 * 100) + '%',
            width: (timeline.end_time - timeline.start_time) / max * scale / 100 * 100 + '%',
            background: (selectedTimelineId == timeline.id ? "linear-gradient(to right, #f76b1c, #fb62a2)" : triggeredColor)
        };
        let slStyle = {
            left: "2px",
            background: (selectedTimelineId == timeline.id ? '#F76B1C': triggeredColor)
        };

        let srStyle = {
            right: "0px",
            background: (selectedTimelineId == timeline.id ? '#FB62A2': triggeredColor)
        };
        if (this.handleLeft){
            this.handleLeft.css({
                left: (timeline.start_time / max * scale / 100 * 100) + '%',
                background: timeline.triggeredcolor
            });
            this.handleRight.css({
                left: (timeline.end_time / max * scale / 100 * 100) + '%',
                background: timeline.triggeredcolor
            });
        }
        return (
            <div ref="timeline" onClick={() => selecteWidgetTimeline(timeline)} className={"widget-timeline " + (timeline.focus ? "focusTimeline" : "")} style={rStyle}>
                <a href='#' className={"ui-slider-handle ui-slider-handle-left " + (selectedTimelineId == timeline.id ? "focusTimeline" : "")} style={srStyle}>
                </a>
                <a href='#' className={"ui-slider-handle ui-slider-handle-right " + (selectedTimelineId == timeline.id ? "focusTimeline" : "")} style={slStyle}>
                </a>
            </div>
        )
    }
}
const mapStateToProps = ({ editor,widgets}) => {
  const pageId = editor.selectedPageId;
  return {
      selecteWidgetTimeline: editor.selecteWidgetTimeline,
      updateTimeline: editor.updateTimeline,
      updateTimelines: editor.updateTimelines,
      widgets: widgets.filter(w => w.page_id === pageId),
  };
};

const mapDispatchToProps = (dispatch) => {
  return bindActionCreators(timelineActions, dispatch);
};


export default connect(mapStateToProps, mapDispatchToProps)(UsedTimeline);
// module.exports = UsedTimeline;
